//
//  CalendarViewModel.swift
//  DaGlass
//
//  Created by 李然 on 2023/4/7.
//

import UIKit
import SwiftDate
import EarbudsDatabase

public enum CalendarType {
    case useTime
    
    var dbModelType: (Storable).Type {
        switch self {
        case .useTime:
            return UsetimeModel.self
        }
    }
}

open class CalendarModel {
    
    public enum ModelType: Int {

        /// 补齐的Model
        case empty = 0
        
        /// 月内正常的Model
        case normal = 1
        
        /// 未来日期
        case future = 2
    }
    
    public let type: ModelType
    
    public init(type: ModelType) {
        self.type = type
    }
    
    public var day = 0
    public var month = 0
    public var year = 0
    
    public var progress: Float = 0.0
    
    /// 是否是被点击状态
    public var isSelected: Bool = false
    
    public var isEmpty: Bool {
        return self.type == .empty
    }

}

public struct CalendarSectionModel {
    public let year: Int
    public let month: Int
    public let lineCount: Int
    public let items: [CalendarModel]
    
    public var monthFirstDay: Date {
        return Date(year: year, month: month, day: 1, hour: 1, minute: 1)
    }
}

public class CalendarViewModel: ViewModel {
    
    deinit {
        log.debug(#function)
    }
    
    public let calendarType: CalendarType
    public let defaultDate: Date
    
    public init(calendarType: CalendarType, defaultDate: Date) {
        self.calendarType = calendarType
        self.defaultDate = defaultDate
        
        super.init()
        
        getCalendarDatas()
    }
    
    public var calendarSections: [CalendarSectionModel] = []
    
    /// 被点击的
    public var selectedItem: CalendarModel?
    
    public var selectIndexPath: IndexPath?
    
    public func getCalendarDatas() {
        
        var months = [String]()
        var datas = [[CalendarModel]]()
        let nowYear = Date().year
        let nowMonth = Date().month
        let firstDate = getFirstDataDate()
        var numberMonths = 0
        while 0 < nowMonth {
            
            guard let calculatedDate = Calendar.current.date(byAdding: .month, value: numberMonths, to: firstDate) else {
                continue
            }
            
            let days = getYearWithMonthQueryDays(date: calculatedDate)
            let month = calculatedDate.toString(.custom("yyyy-MM"))
            months.append(month)
            datas.append(days)
            
            numberMonths += 1
            if calculatedDate.year == nowYear && calculatedDate.month == nowMonth {
                break
            }
        }
        
        calendarSections.removeAll()
        for (i, monthString) in months.enumerated() {
            let monthComp = monthString.components(separatedBy: "-")
            let year = Int(monthComp[0]) ?? 0
            let month = Int(monthComp[1]) ?? 0
            
            var items = datas[i]
            
            for (j, item) in items.enumerated() {
                item.year = year
                item.month = month
                item.day = j + 1
            }
            
            // 插入空白cell
            let firstDate = Date(year: year, month: month, day: 1, hour: 0, minute: 0)
            let firstWeek = firstDate.weekday
            
            // 刚好是周日开始就不需要插入空白
            if firstWeek > 1 {
                for _ in 1 ..< firstWeek {
                    items.insert(CalendarModel(type: .empty), at: 0)
                }
            }
            
            var lineCount = items.count / 7
            if items.count % 7 > 0 {
                lineCount += 1
            }
            
            while items.count < 42 {
                items.append(CalendarModel(type: .empty))
            }
        
            let sectionModel = CalendarSectionModel(year: year,
                                                    month: month,
                                                    lineCount: lineCount,
                                                    items: items)
            calendarSections.append(sectionModel)
        }
        
    }
    
    private func getFirstDataDate() -> Date {
        return EasepodsDB.queryFirst(type: self.calendarType.dbModelType)?.date ?? Date()
    }
    
    private func getYearWithMonthQueryDays(date: Date) -> [CalendarModel] {
        
        let startMonth = date.dateAtStartOf(.month)
        let month = EasepodsDB.queryMonth(type: self.calendarType.dbModelType, from: startMonth)
        
        return month.map { model in
            if model.date > Date() {
                return CalendarModel(type: .future)
            }
            let cModel = CalendarModel(type: .normal)
            if defaultDate.compare(.isSameDay(model.date)) {
                cModel.isSelected = true
                selectedItem = cModel
            }
            return cModel
        }
    }
    
    public func numberOfSections() -> Int {
        return calendarSections.count
    }

    public func numberOfItemsInSection(section: Int) -> Int {
        return calendarSections[section].items.count
    }
    
    public func cellForItemAtCellModel(indexPath: IndexPath) -> CalendarModel {
        return calendarSections[indexPath.section].items[indexPath.row]
    }
    
    public func getDetaultCellIndexPath() -> IndexPath {
        for (sec, section) in calendarSections.enumerated() {
            guard section.year == self.defaultDate.year, section.month == self.defaultDate.month else {
                continue
            }
            for (row, item) in section.items.enumerated() {
                if item.day == self.defaultDate.day {
                    return IndexPath(row: row, section: sec)
                }
            }
        }
        return IndexPath(row: 0, section: 0)
    }
}
